package com.sxhuayuan.parking.entity;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sxhuayuan.parking.config.InvoiceStatus;
import com.sxhuayuan.parking.config.PayMode;
import com.sxhuayuan.parking.config.PayStatus;
import com.sxhuayuan.parking.config.Platform;
import com.sxhuayuan.parking.utils.DateUtils;

/**
 * 停车费订单表
 */
@Entity
@Table(name = "hypk_order", indexes = { @Index(columnList = "sn"), @Index(columnList = "paytime") })
public class Order extends BaseEntity {

	private static final long serialVersionUID = -2857800201632171348L;

	public enum Method {
		// 预支付
		prepay,
		// 出口扫码
		exit,
		// 无感支付
		partnerpay,
		// 无牌车扫码
		anno,
		// 人工缴费
		manual,
	}

	private Method method;

	/** 应收(实付)金额，已减去优惠金额 */
	private BigDecimal money;
	/** 手续费 */
	private BigDecimal serviceCharge;
	/** 退款金额 */
	private BigDecimal refundMoney;
	/** 订单编号 */
	private String sn;
	/** 华贝订单号 */
	private String tradeNo;
	/** 车场订单号，可为空，但不可重复 */
	private String lotOrderNo;
	/** 子商户号 */
	private String mchid;
	/** 支付状态 */
	private PayStatus payStatus;
	/** 订单ip地址 */
	private String ip;
	/** 车牌号 */
	private String carPlate;
	/** 支付类别 */
	private Platform platform;
	/** 支付方式 */
	private PayMode payMode;
	// 入场唯一序列，来自入场记录表
	private Long uniqueId;
	/** 第三方 入场时间 yyyy-MM-dd HH:mm:ss */
	private Date entertime;
	// 本次开始计费时间
	private Date starttime;
	/** 截止计费时间 yyyy-MM-dd HH:mm:ss */
	private Date endtime;
	/** 备注 */
	private String remark;
	/** 车场名称 */
	private String parkingLotName;
	/** 车场编号 */
	private String parkingLotSn;
	/** 是否抬杆成功 */
	private Boolean isRiseSuccess = false;
	/** 支付时间 */
	private Date paytime;
	// 支付通道id
	private String pluginId;
	// 记录交易时的appid，方便统计对账
	private String appid;
	/** 停车信息，originalParkingInfo.id */
	@JsonIgnore
	private Long parkingInfoId;
	/** 停车场标识 */
	@JsonIgnore
	private ParkingLot parkingLot;
	/** 出口标识，可能为空，如预支付时 */
	@JsonIgnore
	private Long exitId;
	/** 用户，不可为空 */
	@JsonIgnore
	private Long memberId;
	/** 代理 */
	@JsonIgnore
	private Long agentId;
	/** 优惠券 */
	private Long couponId;
	/** 车场优惠金额 */
	private BigDecimal totalDiscount;

	/** 订单发票状态,默认未开发票 */
	private InvoiceStatus invoiceStatus=InvoiceStatus.unInvoiced;

	@NotNull
	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	@NotNull
	@Column(nullable = false, scale = 2, precision = 10)
	public BigDecimal getMoney() {
		return money;
	}

	public void setMoney(BigDecimal money) {
		this.money = money;
	}

	@NotNull
	@Column(nullable = false, columnDefinition = "decimal(10,2) default '0.00'")
	public BigDecimal getServiceCharge() {
		return serviceCharge;
	}

	public void setServiceCharge(BigDecimal serviceCharge) {
		this.serviceCharge = serviceCharge;
	}

	@NotNull
	@Column(nullable = false, scale = 2, precision = 10)
	public BigDecimal getRefundMoney() {
		return refundMoney;
	}

	public void setRefundMoney(BigDecimal refundMoney) {
		this.refundMoney = refundMoney;
	}

	@NotNull
	public PayStatus getPayStatus() {
		return payStatus;
	}

	public void setPayStatus(PayStatus payStatus) {
		this.payStatus = payStatus;
	}

	@Column(nullable = false)
	public Boolean getIsRiseSuccess() {
		return isRiseSuccess;
	}

	public void setIsRiseSuccess(Boolean isRiseSuccess) {
		this.isRiseSuccess = isRiseSuccess;
	}

	@Column(length = 24)
	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	@NotNull
	@Column(length = 64, updatable = false)
	public String getSn() {
		return sn;
	}

	public void setSn(String sn) {
		this.sn = sn;
	}

	@Column(length = 24, updatable = false)
	public String getCarPlate() {
		return carPlate;
	}

	public void setCarPlate(String carPlate) {
		this.carPlate = carPlate;
	}

	public Platform getPlatform() {
		return platform;
	}

	public void setPlatform(Platform platform) {
		this.platform = platform;
	}

	public PayMode getPayMode() {
		return payMode;
	}

	public void setPayMode(PayMode payMode) {
		this.payMode = payMode;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public String getMchid() {
		return mchid;
	}

	public void setMchid(String mchid) {
		this.mchid = mchid;
	}

	public String getTradeNo() {
		return tradeNo;
	}

	public void setTradeNo(String tradeNo) {
		this.tradeNo = tradeNo;
	}

	@Column(length = 64)
	public String getLotOrderNo() {
		return lotOrderNo;
	}

	public void setLotOrderNo(String lotOrderNo) {
		this.lotOrderNo = lotOrderNo;
	}

	public Date getPaytime() {
		return paytime;
	}

	public void setPaytime(Date paytime) {
		this.paytime = paytime;
	}

	public Date getEntertime() {
		return entertime;
	}

	public void setEntertime(Date entertime) {
		this.entertime = entertime;
	}

	public Date getStarttime() {
		return starttime;
	}

	public void setStarttime(Date starttime) {
		this.starttime = starttime;
	}

	public Date getEndtime() {
		return endtime;
	}

	public void setEndtime(Date endtime) {
		this.endtime = endtime;
	}

	// @JoinColumn(name = "parking_info_id")
	// @OneToOne(fetch = FetchType.LAZY)
	// public OriginalParkingInfo getParkingInfo() {
	// return parkingInfo;
	// }
	//
	// public void setParkingInfo(OriginalParkingInfo parkingInfo) {
	// this.parkingInfo = parkingInfo;
	// }

	public Long getParkingInfoId() {
		return parkingInfoId;
	}

	public void setParkingInfoId(Long parkingInfoId) {
		this.parkingInfoId = parkingInfoId;
	}

	public Long getMemberId() {
		return memberId;
	}

	public void setMemberId(Long memberId) {
		this.memberId = memberId;
	}

	public Long getAgentId() {
		return agentId;
	}

	public void setAgentId(Long agentId) {
		this.agentId = agentId;
	}

	public Long getCouponId() {
		return couponId;
	}

	public void setCouponId(Long couponId) {
		this.couponId = couponId;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "parking_lot_id")
	public ParkingLot getParkingLot() {
		return parkingLot;
	}

	public void setParkingLot(ParkingLot parkingLot) {
		this.parkingLot = parkingLot;
	}

	// @ManyToOne(fetch = FetchType.LAZY)
	// @JoinColumn(name = "parking_lot_exit_id")
	// public ParkingLotExit getParkingLotExit() {
	// return parkingLotExit;
	// }
	//
	// public void setParkingLotExit(ParkingLotExit parkingLotExit) {
	// this.parkingLotExit = parkingLotExit;
	// }

	@Column(length = 32)
	public String getPluginId() {
		return pluginId;
	}

	public void setPluginId(String pluginId) {
		this.pluginId = pluginId;
	}

	@Column(length = 32)
	public String getParkingLotSn() {
		return parkingLotSn;
	}

	public void setParkingLotSn(String parkingLotSn) {
		this.parkingLotSn = parkingLotSn;
	}

	@Column(length = 32)
	public String getParkingLotName() {
		return parkingLotName;
	}

	public void setParkingLotName(String parkingLotName) {
		this.parkingLotName = parkingLotName;
	}

	public Long getExitId() {
		return exitId;
	}

	public void setExitId(Long exitId) {
		this.exitId = exitId;
	}

	public Long getUniqueId() {
		return uniqueId;
	}

	public void setUniqueId(Long uniqueId) {
		this.uniqueId = uniqueId;
	}

	@Column(length = 32)
	public String getAppid() {
		return appid;
	}

	public void setAppid(String appid) {
		this.appid = appid;
	}

	@Column(nullable = false, columnDefinition = "decimal(10,2) default '0.00'")
	public BigDecimal getTotalDiscount() {
		return totalDiscount;
	}

	public void setTotalDiscount(BigDecimal totalDiscount) {
		this.totalDiscount = totalDiscount;
	}

	/**
	 * 已支付金额=应付-已退款
	 * 
	 * @return
	 */
	@Transient
	public BigDecimal getPaidMoney() {
		return money.subtract(refundMoney);
	}
	
	@Transient
	public Long getParkTime() {
		if (this.endtime == null || this.entertime == null) {
			return 0L;
		}
		return DateUtils.diff(entertime, this.endtime, Calendar.MINUTE);
	}

	public InvoiceStatus getInvoiceStatus() {
		return invoiceStatus;
	}

	public void setInvoiceStatus(InvoiceStatus invoiceStatus) {
		this.invoiceStatus = invoiceStatus;
	}
}
